package jwtx

import (
	"errors"

	"github.com/golang-jwt/jwt/v5"
)

var ErrorClaimsType = errors.New("ClaimsType")
var Secret = PrivateKey(privateKey)

func Token[T jwt.Claims](secret any, v T, methods ...jwt.SigningMethod) (string, error) {
	var method jwt.SigningMethod = jwt.SigningMethodEdDSA
	if len(methods) > 0 {
		method = methods[0]
	}

	claims := jwt.NewWithClaims(method, v)

	return claims.SignedString(secret)
}

func Parse(secret any, tokenString string, methods ...jwt.SigningMethod) (jwt.MapClaims, error) {
	var method jwt.SigningMethod = jwt.SigningMethodEdDSA
	if len(methods) > 0 {
		method = methods[0]
	}

	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (any, error) {
		return secret, nil
	}, jwt.WithValidMethods([]string{method.Alg()}))
	if err != nil {
		return nil, err
	}

	if claims, ok := token.Claims.(jwt.MapClaims); token.Valid && ok {
		return claims, nil
	}

	return nil, ErrorClaimsType
}

func ParseClaims[T jwt.Claims](secret any, tokenString string, methods ...jwt.SigningMethod) (T, error) {
	var method jwt.SigningMethod = jwt.SigningMethodEdDSA
	if len(methods) > 0 {
		method = methods[0]
	}

	var t T
	claimsPtr := any(&t).(jwt.Claims)

	token, err := jwt.ParseWithClaims(tokenString, claimsPtr, func(token *jwt.Token) (any, error) {
		return secret, nil
	}, jwt.WithValidMethods([]string{method.Alg()}))
	if err != nil {
		return t, err
	}

	if token.Valid {
		return t, nil
	}

	return t, ErrorClaimsType
}
